链接

用户手册

参考

Apache Tomcat 开发

Apache Tomcat 5.5 Servlet/JSP 容器

如何设置SSL

Printer Friendly Version
print-friendly
version
速成

文档说明:本文件适用于用JSSE设置Tomcat的SSL。 如果使用 APR, Tomcat是通过 OpenSSL来实现SSL,设置会不同。

在下面的描述中使用变量名$CATALINA_HOME来代指Tomcat5所安装的目录地址, 这是一个基础目录(base directory),其他的相关路径由它而派生。不过,如果你已经把Tomcat 设置成多个体实例(multiple instances),并且设立了一个$CATALINA_BASE目录, 那么你就应使用$CATALINA_BASE而不是$CATALINA_HOME作为参照。

你需要按照下列简单步骤在Tomcat 5上安装和配置SSL支持。更多信息,请阅读这个帮助的其余部分。

  1. 如果你在使用1.3 JVM,从http://java.sun.com/products/jsse/ 下载JSSE 1.0.3 (或其后的版本), 然后,或者把它作为系统上installed extension,或者把它设置为一个环境变量 JSSE_HOME,让它指向你所安装JSSE的目录。


  2. 通过执行下面的命令产生一个认可的keystore。
    %JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA

    Unix

    %JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA

    并指定一个密码值为"changeit"。


  3. 把$CATALINA_HOME/conf/server.xml中的 "SSL HTTP/1.1 Connector" 去掉注释,并根据需要修改。


SSL简介

SSL, 或者Secure Socket Layer,是一种允许web浏览器和web服务器通过一个安全的连接进行 交流的技术。这意味着将被发送的数据在一端被翻译成密码,传送出去,然后在另一端解开密码, 再进行处理。这是一个双向的过程,也就是浏览器和服务器都需要在发送数据之前对它们进行加密。

SSL协定的另一个重要方面是认证(Authentication)。这就是说,在你开始试图通过一个安全连接 与一个web服务器交流的时候,这个服务器会要求你的浏览器出示一组证件,通过“鉴定”的方式来证明这 就是你所声明的网站。在某些情况下,服务器还会要求你的web浏览器的认证书,证明你就是你所说的那 个人。这就是所知的“客户认证”,尽管实际情况中,更多地用在商务-对-商务(B2B)交易,而不是对个人 用户。大多数有SSL功能的web服务器不要求客户认证(Client Authentication)。

SSL 和 Tomcat

必须要注意,配置Tomcat来利用secure sockets仅仅在它作为一个独立的web服务器时才有必要。 当Tomcat主要作为在另外一个web服务器,如Apache 或Microsoft IIS, 后面的Servlet/JSP容器 运行时,通常有必要把主要的web服务器配置来处理与用户的SSL连接。通常,这个服务器会对所有的 SSL-相关的功能进行交涉,然后再把对Tomcat容器的请求解密后传递过去。同样,Tomcat会返回 明码的回应,这个回应将被加密后才被送到用户浏览器。在这样的环境下,Tomcat知道与主要web服务器 和客户的交流是通过一个安全连接才发生的(因为你的程序需要询问这些情况),但是它本身并没有参与 加密和解密。

认证书:Certificate

为了能实施SSL,一个web服务器对每个接受安全连接的外部接口(IP 地址)必须要有相应的认 证书(Certificate)。关于这个设计的理论是一个服务器必须提供某种合理的保证以证明这个服务器的 主人就是你所认为的那个人,特别是在接收任何敏感信息之前要这样做。关于Certificates的更广泛 的解释超过了这个文档资料的范围,就把一个认证书当作一个英特网地址的“数码驾驶执照”。这个认证书 要陈述与这个网站相关联的公司,以及这个网站的所有者或系统管理员的一些基本联系信息。

这个"驾驶执照"由所有人以密码方式签字,其他人非常难伪造。对于进行电子商务 (e-commerce)的网站,或其他身份认证至关重要的任何商业交易,认证书要向大家所熟知的认证权威 (Certificate Authority (CA))如VeriSign或Thawte来购买。这样的认证书可用电子 技术证明属实——实际上,认证权威单位会担保它发出的认证书的真实性,如果你信任发出认证书的 认证权威单位的话,你就可以相信这个认证书是有效的。

在许多情况下,认证并不是真正使人担忧的事。系统管理员或许只想要保证被服务器传送和接收的 数据是秘密的,不会被连接线上的偷窃者盗窃到。庆幸的是,Java提供相对简单的被称 为keytool的命令行工具,可以简单地产生“自己签名”的认证书。自己签名的认证书 只是用户产生的认证书,没有正式在大家所熟知的认证权威那里注册过,因此不能确保它的真实性。 认证也许很重要,也许不重要,完全决定于你的需要。

使用SSL需要考虑的地方

用户第一次试图到你的网站访问被安全保卫的页面时,他(她)通常会被要求提供关于认证的 详细信息(如公司名称和联系姓名),并询问他(她)是否愿意接受这个认证的合法性,并继续进行交易。 一些浏览器会提供一个选项来永久地接受所给的认证的合法性,这样一来用户就不用在每次访问你的网站 时麻烦地去填写认证信息。有的浏览器没有这一选项。一旦用户认可后,这个认证至少在整个浏览器 会话期间被认为是合法的。

虽然SSL协议的设计尽量做到既安全又高效,但是加密和解密是复杂耗时的计算过程。通常没有必要让整个 网站都通过SSL来传输,开发人员可以选择部分网页用SSL,部分网页不用SSL。对于一个相对繁忙的网站 来说,可以选择保护那些比较敏感的信息,如登陆、个人信息、购物车、付账、信用卡等。那些网页只要 把网页地址里http:改为https:,浏览器就会自动把信息按照指定的 协议传输出去。

最后,使用根据网名决定的虚拟主机来进行安全连接可能会出现问题。这是SSL协定本身的设计局限。 SSL handshake,就是客户浏览器接受服务器认证,在HTTP请求访问之前必须产生。因此,包含虚拟 主机名字的请求信息在认证之前不能被确定,所以不可能给单个IP地址分配多个认证书。如果在单个IP 地址上的所有的虚拟主机需要对照同一个认证书来认证的话,再添加多个虚拟主机不应该干扰服务器上 正常的SSL操作。不过要当心,大多数的客户浏览器会按认证书上列出的domain names(主要是官方的, CA-签署的认证书)对照比较服务器的domain name。如果领域名(domain names)不相配,这些浏览器 会向客户端用户显示警告。总的来说,只有address-based虚拟主机通常和SSL一起在生产环境中 被使用。

设置
检查你是否需要下载 JSSE

Java 1.4或更新的版本已经包括了JSSE。如果你使用 1.4或更新版本,你不需要另外下载JSSE。 你可以跳过本节

从下面的网站下载Java Secure Socket Extensions (JSSE) 版本 1.0.3或更新版。 http://java.sun.com/products/jsse/.

在扩展这个软件包后,有两种方法让Tomcat可以使用它(选择其中之一):

  • 通过把所有这三个JAR文件(jcert.jar , jnet.jar , 和 jsse.jar)复制到$JAVA_HOME/jre/lib/ext 目录中去,让JSSE成为 安装好的扩充目录
  • 产生一个新的环境变量JSSE_HOME,让它包含绝对路径,指向你拆装(unpacked) JSSE二进制分布的目录。
产生 Keystore

Tomcat 现在只支持 JKSPKCS12 格式的keystores. JKS格式是 Java 的标准 KeyStore格式,它可以用 Java 的 keytool 来产生。这个工具在 Java 的 bin 目录里。 PKCS12 格式时互联网的标准,可以用 OpenSSL 和微软的 Key-Manager来修改。

To import an existing certificate into a JKS keystore, please read the documentation (in your JDK documentation package) about keytool. Note that openssl often adds a readable comments before the key, keytooldoes not support that, so remove the openssl comments if they exist before importing the key using keytool.

使用OpenSSL把一个现存的被你自己CA签署的认证书输入到PKCS12 keystore里面,你会执行象这样的一个命令:

openssl pkcs12 -export -in mycert.crt -inkey mykey.key \
                        -out mycert.p12 -name tomcat -CAfile myCA.crt \
                        -caname root -chain
更深层的情况,请查阅OpenSSL documententation

要从头开始产生一个新的keystore,包含一个自签的认证书,从一个终端命令行执行下面的命令:

视窗

%JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA

Unix

%JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA

( 应该把RSA运算法则作为主要安全运算法则,这保证了与其它服务器和组件的兼容性。)

这个命令会在用户的home directory产生一个叫做" .keystore " 的新文件。要指定一个不同的位置(location)或文件名,在上面所示的keytool 命令里添加-keystore参数,后面紧跟着你的keystore文件的全部路径名。你还需要把 这个新的位置在server.xml配置文件中反映出来,这在后面将有描述。例如:

视窗

%JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA \ 
-keystore \path\to\my\keystore

Unix

%JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA \ 
-keystore \path\to\my\keystore

在执行这个命令后,你首先被要求出示keystore密码。Tomcat使用的默认密码是 " changeit "(全都是小写字母),如果你愿意,你可以指定你自己的 密码。你还需要在server.xml配置文件里指定自己的密码,这在以后会有描述。

下一步,你会被要求出示关于这个认证书的一般性信息,如公司,联系人名称,等等。这些信息会 显示给那些试图访问你程序里安全网页的用户,以确保这里提供的信息与他们期望的相对应。

最后,你会被要求出示密钥(key)密码,也就是这个认证书所特有的密码(与其它的 储存在同一个keystore文件里的认证书不同)。你必须在这里使用与keystore 密码相同的密码。(目前,keytool会提示你按ENTER键会自动帮你做这些)。

如果一切顺利,你现在就拥有了一个可以被你的服务器使用的有认证书的keystore文件。

注意: 你的 private key 的密码和 keystore 的密码应该相同。 如果不同的话你会得到一下错误信息: java.io.IOException: Cannot recover key 这是一个已知的错误,详细请看: Bugzilla issue 38217

Edit the Tomcat Configuration File

最后的步骤是把你的secure socket配置在$CATALINA_HOME/conf/server.xml文件里, $CATALINA_HOME代表你在其中安装Tomcat 5 的目录。一个例子是SSL连接器 的<Connector>元素被包括在和Tomcat一起安装的缺省server.xml文件里。 它看起来象是这样:

<-- Define a SSL Coyote HTTP/1.1 Connector on port 8443 -->
<!--
<Connector 
           port="8443" minProcessors="5" maxProcessors="75"
           enableLookups="true" disableUploadTimeout="true"
           acceptCount="100" debug="0" scheme="https" secure="true";
           clientAuth="false" sslProtocol="TLS"/>
-->

你会注意到Connector元素本身,其默认形式是被注释掉的(commented out),所以你需要把它周围 的注释标志删除掉。然后,你可以根据需要客户化(自己设置)特定的属性。关于各种选项的详细信息, 请查阅Server Configuration Reference 。下面的讨论 仅仅涵盖设置SSL通信(communication)时大家最感兴趣的那些属性。

这个port属性(默认值是8443)是 TCP/IP端口数码,Tomcat在其上监听安全连接。 你可以把它更改成任何你愿意要的数值(如默认的https通信,数目是443)。不过,在许 多操作系统中,要想在比1024小的端口数码上运行Tomcat,需要特殊的设置(它超出了这个文档资料 的范围)。

如果你在这里更改端口数值,你还必须更改在non-SSL连接器上的redirectPort 这个属性特定的值。这允许Tomcat自动地redirect那些试图访问有安全限制页面的用户,指明根据 Servlet 2.4 Specification要求,SSL是必需的。

有一些额外的选项被用来配置SSL协定。依赖于你早先怎样配置你的keystore,你也许需要添加或更改下列属性值:

属性 描述
clientAuth 如果你想要Tomcat要求所有的SSL客户在使用这个socket时出示用户认证书,把这个值设定为 true 。如果你想要Tomcat要求出示用户认证书,但是如果没有认证书也可以, 就把这个值设定为want
keystoreFile 如果你产生的keystore文件不在Tomcat期望的默认地方(一个叫做.keystore 的文件在Tomcat运行的主目录),就添加这个属性。你可以指定一个绝对路径名称, 或者一个由$CATALINA_BASE环境变量而派生的相对路径名称。
keystorePass 如果你使用一个不同的keystore(以及认证书)密码,而不是Tomcat期望的密码 (就是changeit),添加这个元素。
keystoreType 如果使用一个PKCS12 keystore的话,就添加这个element。 有效的值是JKS 和 PKCS12 。
sslProtocol 要在这个socket上被使用的加密/解密协定。如果你在使用Sun的JVM,我们不提倡更改 这个值。据报道,TLS协定的IBM's 1.4.1 实现与一些通用的浏览器不兼容。 如果是这样,就使用value SSL
ciphers 这个socket允许使用的由逗号分隔开的加密密码列单。默认的情况下,任何可用的密码都允许被使用。
algorithm 可用的X509算法。默认是Sun的实现( SunX509 )。 对于IBM JVMs,你应该使用值 IbmX509。对于其他卖主,查阅JVM文档资料来 找正确的值。
truststoreFile 用来验证用户认证书的TrustStore文件。
truststorePass 访问TrustStore的密码。默认值就是keystorePass的值。
truststoreType 如果你在使用与KeyStore不同格式的TrustStore,添加这个元素。 合法的值是JKSPKCS12
keyAlias 如果 keystore 里面有多个 key,你可以为用这个选项为加入的 key 起一个名字。 如果没有指定名字,使用时 keystore 内的第一个 key 将会被使用。

在完成这些配置更改后,你必须象通常那样重新启动Tomcat,然后你就可以工作了。 你应该可以通过SSL访问Tomcat支持的任何web应用程序。例如,试一下下面的指令:

https://localhost:8443

你应该看到通常的Tomcat splash页面(除非你修改过ROOT web应用程序)。如果不行的话, 下面的章节包含一些排除故障的提示。

安装和获取认证权威颁发的认证书

要从认证权威(如verisign.com, thawte.com 或 trustcenter.de)获得并安装认证书, 你应该先阅读前面章节,然后再按照下面的指示进行:

产生一个认证签名请求 (CSR)

为了从你选择的认证权威那里获得认证书,你必须产生一个所谓的认证签名请求(Certificate Signing Request (CSR))。这个认证签名请求被认证权威用来产生鉴定你的网站是“安全的”的认证书。 按照下列步骤产生一个CSR:

  • 产生一个局部认证书(如前面章节描述那样):
    keytool -genkey -alias tomcat -keyalg RSA \ 
       -keystore &lt;your_keystore_filename&gt;
    注意:在某些情况下, 要产生一个工作认证书,你必须在“"first- and lastname" field 键入你的网站的域名 (例如www.xwood.net)。
  • 然后用下列指令产生CSR :
    keytool -certreq -keyalg RSA -alias tomcat 
    -file certreq.csr \ 
       -keystore &lt;your_keystore_filename&gt;

执行这个命令之后你会得到一个文件叫 certreq.csr。然后你可以到发送到认证权威, 然后你就可以得到你的认证书。具体步骤可以参考他们的网站的帮助文件。

导入认证书

现在你有了认证书,你可以把它输入到你局部的keystore里。首先你必须输入一个叫做证书链 Chain Certificate 或 Root Certificate 到你的 keystore 里去。在这之后,你可以开始 输入你的认证书。

  • 从你获得认证书的认证权威那里下载一个Chain Certificate 。
    For Verisign.com commercial certificates go to: http://www.verisign.com/support/install/intermediate.html
    For Verisign.com trial certificates go to: http://www.verisign.com/support/verisign-intermediate-ca/Trial_Secure_Server_Root/index.html For Trustcenter.de go to: http://www.trustcenter.de/certservices/cacerts/en/en.htm#server
    对于Thawte.com , 去http://www.thawte.com/certs/trustmap.html下载
  • 把Chain Certificate 输入到你的keystore里边
    keytool -import -alias root -keystore &lt;your_keystore_filename&gt; \ 
       -trustcacerts -file &lt;filename_of_the_chain_certificate&gt;
  • 最后输入你的新的认证书
    keytool -import -alias tomcat -keystore &lt;your_keystore_filename&gt; \ 
       -trustcacerts -file &lt;your_certificate_filename&gt;
Troubleshooting

这里是一些你在设置SSL通信时也许会遇到的常见问题,以及如何解决它们。

  • 我在我的日志文件中得到"java.security.NoSuchAlgorithmException"错误。

    JVM找不到JSSE JAR 文件。按照所有的指导说明 下载并安装JSSE

  • 当Tomcat启动时,我得到一个象 "java.io.FileNotFoundException: {some-directory}/{some-file} not found"的异常。

    一个可能的解释是Tomcat不能在它要找的地方找到 keystore文件。在默认的情况下, Tomcat预计 keystore文件在Tomcat运行的用户主目录里被命名为.keystore。 如果 keystore存放在别的什么地方,你需要向Tomcat配置文件里的 &lt;Factory&gt;元素添加一个 keystoreFile属性。

  • 当Tomcat启动时,我得到一个象"java.io.FileNotFoundException: Keystore was tampered with, or password was incorrect"的异常。

    如果没有其他人 试图 修改你的 keystore 文件,最可能的情况是 Tomcat 用了错误的密码。你可以尝试重新产生 keystore 文件,或修改 Tomcat 设置文件里 <Connector> 元素的 keystorePass 属性,还请记住密码是分大小写的。

如果你仍然有问题,一个好的地方你可找到帮助是 TOMCAT-USER 邮件列表。你可以 用下面的地址订阅。 http://tomcat.apache.org/lists.html.

Miscellaneous Tips and Bits

你可以用下面的办法获取用户 SSL session 的 ID:
String sslID = (String)request.getAttribute("javax.servlet.request.ssl_session");
你可从下面的网址获得更多这方面的信息: Bugzilla.


Copyright © 1999-2006, Apache Software Foundation